﻿using Commons.ASPNETCore;
using FileService.Domain;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Minio.DataModel;
using System.Security.Claims;

namespace FileService.WebApi.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class UploaderController : ControllerBase
    {

        private readonly FSDomainService domainService;
        private readonly IFSRepository repository;
        public UploaderController(FSDomainService domainService, IFSRepository repository)
        {
            this.domainService = domainService;
            this.repository = repository;
        }

        [HttpGet]
        public IActionResult Hello()
        {
            string id = this.User.FindFirst(ClaimTypes.NameIdentifier)!.Value;
            string userName = this.User.FindFirst(ClaimTypes.Name)!.Value;

            IEnumerable<Claim> roleClaims = this.User.FindAll(ClaimTypes.Role);
            string roleNames = string.Join(separator: ',', roleClaims.Select(c => c.Value));

            return Ok($"id={id},userName={userName},roleNames ={roleNames}");
        }

        /// <summary>
        /// 检查是否有和指定的大小和SHA256完全一样的文件
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<Result> FileExists(long fileSize, string sha256Hash)
        {
            var item = await repository.FindFileAsync(fileSize, sha256Hash);
            if (item == null)
            {
                return Result.Success(new FileExistsResponse(IsExists: false, null));
            }
            else
            {
                return Result.Success(new FileExistsResponse(true, item.RemoteUrl));
            }
        }

        //todo: 做好校验，参考OSS的接口，防止被滥用
        //todo：应该由应用服务器向fileserver申请一个上传码（可以指定申请的个数，这个接口只能供应用服务器调用），
        //页面直传只能使用上传码上传一个文件，防止接口被恶意利用。应用服务器要控制发放上传码的频率。
        //todo：再提供一个非页面直传的接口，供服务器用
        [HttpPost]
        [RequestSizeLimit(1_600_000_000)]
        public async Task<Result> Upload([FromForm] UploadRequest request, CancellationToken cancellationToken = default)
        {
            var file = request.File;
            string fileName = file.FileName;
            using Stream stream = file.OpenReadStream();

            (var upItem, var IsExists) = await domainService.UploadAsync(stream, fileName, cancellationToken);
            if (!IsExists)
            {
                await repository.Add(upItem);
            }
            return Result.Success(new { upItem.FileName,upItem.RemoteUrl});
        }
    }
}
